﻿namespace FFF.Test.Application.Repositories
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data;
    using System.IO;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;
    using Abp.Application.Services.Dto;
    using Abp.AutoMapper;
    using Abp.Domain.Entities;
    using Abp.EntityFrameworkCore;
    using Abp.EntityFrameworkCore.Extensions;
    using Abp.EntityFrameworkCore.Repositories;
    using Abp.Linq.Dynamic.Extensions;
    using Abp.ObjectMapping;
    using Abp.UI;
    using AutoMapper.QueryableExtensions;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using Newtonsoft.Json;
    using FFF.Test.Application.AppServices.PublicService.Grid;
    using FFF.Test.DataAccess.Framework;
    using FFF.Test.DataAccess.Framework.Configuration;
    using FFF.Test.Entity.Demo.View;
    using FFF.Test.Entity.Framework.Entity;
    using FFF.Test.Util.Consts;
    using FFF.Test.Util.Web;
    using Ydm.Extensions;
    using Ydm.Helper;
    using Ydm.QueryFilter.Core;
    using Z.Expressions;
    using IObjectMapper = Abp.ObjectMapping.IObjectMapper;

    /// <summary>
    /// response基类
    /// </summary>
    /// <typeparam name="TEntity">实体对象</typeparam>
    /// <typeparam name="TPrimaryKey">主键的类型</typeparam>
    /// <typeparam name="TCreateInput">实体输入的类型</typeparam>
    /// <typeparam name="TUpdateInput">实体输出类型</typeparam>
    /// <typeparam name="TEntityDto">实体展示的类型</typeparam>
    /// <typeparam name="TView">view的类型</typeparam>
    /// <typeparam name="TViewDto">viewDto的展示</typeparam>
    public abstract class YdmAbpRepositoryBase<TEntity, TPrimaryKey, TCreateInput, TUpdateInput, TEntityDto, TView, TViewDto> :
        EfCoreRepositoryBase<MyDbContext, TEntity, TPrimaryKey>,
        IRepositoriesBase<TEntity, TPrimaryKey, TCreateInput, TUpdateInput, TEntityDto, TView, TViewDto>
        where TEntity : BaseEntity<TPrimaryKey>
        where TView : class, IEntity<TPrimaryKey>, new()
        where TViewDto : class
        where TCreateInput : class, IEntityDto<TPrimaryKey>
        where TUpdateInput : class, IEntityDto<TPrimaryKey>
        where TEntityDto : class, IEntityDto<TPrimaryKey>
    {
        private readonly IObjectMapper _objectMapper;
        private readonly IDbContextProvider<MyDbContext> _dbContextProvider;

        /// <summary>
        /// Initializes a new instance of the <see cref="YdmAbpRepositoryBase{TEntity, TPrimaryKey, TCreateInput, TUpdateInput, TEntityDto,TView, TViewDto}"/> class.
        /// 仓储构造方法 初始化连接 隐射对象
        /// </summary>
        /// <param name="dbContextProvider">数据库连接</param>
        /// <param name="objectMapper">处理映射</param>
        protected YdmAbpRepositoryBase(IDbContextProvider<MyDbContext> dbContextProvider, IObjectMapper objectMapper)
            : base(dbContextProvider)
        {
            this._objectMapper = objectMapper;
            this._dbContextProvider = dbContextProvider;
        }

        /// <summary>
        /// 获取MyDbContext
        /// </summary>
        /// <returns>IQueryable&lt;TView&gt;.</returns>
        /// <remarks>于大明 2020-06-03</remarks>
        public MyDbContext GetDbContextMy()
        {
            return this._dbContextProvider.GetDbContext();
        }

        /// <summary>
        /// db的saveChange
        /// </summary>
        /// <returns>影响行数</returns>
        public virtual Task<int> SaveChangeAsync()
        {
            return this.GetDbContextMy().SaveChangesAsync();
        }

        /// <summary>
        /// 获取视图对象
        /// </summary>
        /// <param name="isDisableFrameWorkFilter">是否禁用框架过滤</param>
        /// <returns>获取视图的实例</returns>
        public virtual IQueryable<TView> GetView(bool isDisableFrameWorkFilter = false)
        {
            var db = this.GetDbContextMy();
            var viewQuery = db.Query<TView>().AsQueryable();

            if (!isDisableFrameWorkFilter)
            {
                if (typeof(TView) == typeof(ViewDemoStudentTe))
                {
                    var viewDemoStudent = viewQuery as IQueryable<ViewDemoStudentTe>;
                    viewDemoStudent = viewDemoStudent.Where(x => x.StudentAge <= 200);
                    viewQuery = viewDemoStudent as IQueryable<TView>;
                }
            }

            return viewQuery;
        }

        /// <summary>
        /// 获取统计视图
        /// </summary>
        /// <typeparam name="TSummaryView">summaryview的视图</typeparam>
        /// <returns>获取视图的实例</returns>
        public IQueryable<TSummaryView> GetSummaryView<TSummaryView>()
            where TSummaryView : class
        {
            var db = this.GetDbContextMy();
            return db.Query<TSummaryView>();
        }

        /// <summary>
        /// 导入数据
        /// </summary>
        /// <param name="inDto">导入对象</param>
        /// <returns>提示信息</returns>
        public virtual async Task<ImportOutDto> ImportExcelAsync(ImportInDto inDto)
        {
            return await this.ImportExcelAsync(inDto, null);
        }

        /// <summary>
        /// 导入数据
        /// </summary>
        /// <param name="inDto">导入对象</param>
        /// <param name="dealView">处理view的视图</param>
        /// <returns>提示信息</returns>
        public virtual async Task<ImportOutDto> ImportExcelAsync(ImportInDto inDto, Action<List<TView>> dealView)
        {
            if (inDto.FilePath.IsNullOrEmpty())
            {
                throw new UserFriendlyException("未找到文件");
            }

            // 读取Excel文件
            string filePath = Server.MapPath($@"~{inDto.FilePath}");

            // 构造列的dic
            Dictionary<string, string> dicColMapper = new Dictionary<string, string>();
            inDto.ColName = Regex.Replace(inDto.ColName, @"\(.*?\)", string.Empty);
            List<string> colNames = inDto.ColName.Split(",").ToList();
            List<string> fieldNames = inDto.FieldName.Split(",").ToList();
            for (int i = 0; i < colNames.Count; i++)
            {
                if (!dicColMapper.Keys.Contains(colNames[i]))
                {
                    dicColMapper.Add(colNames[i], fieldNames[i].ToCamel());
                }
            }

            // 读取table表格转lst
            DataTable dt = YdmExcelHelper.ExcelToDataTable(filePath);

            // 删除文件
            File.Delete(filePath);
            List<TView> views = dt.ToList<TView>(dicColMapper);
            dealView?.Invoke(views);

            // 根据guid
            var objectMapper = base.IocResolver.Resolve<IObjectMapper>();
            var createInputs = objectMapper.Map<List<TCreateInput>>(views);
            foreach (var createInput in createInputs)
            {
                await this.CreateByDtoAsync(createInput);
            }

            ImportOutDto dto = new ImportOutDto()
            {
                StatusCode = 200,
                Title = "提示信息",
                Message = "导入成功"
            };

            return dto;
        }

        /// <summary>
        /// 获取表格数据
        /// </summary>
        /// <param name="inDto">获取表格数据输入dto</param>
        /// <param name="viewType">默认查询的view的类型</param>
        /// <returns>dto对象</returns>
        public virtual async Task<GridResult> GetGridDtoAsync(GetGridListInDto inDto, Type viewType = null)
        {
            if (viewType == null)
            {
                viewType = typeof(TViewDto);
            }

            var result = await this.GetGridDataResult(inDto, viewType);

            GridResult gridResult = new GridResult()
            {
                Rows = result.DataList,
                Total = result.RowCount
            };

            return gridResult;
        }

        /// <summary>
        /// 获取表格汇总数据
        /// </summary>
        /// <param name="inDto">输入Dto</param>
        /// <param name="viewType">默认查询的view的类型</param>
        /// <returns>输出dto</returns>
        public virtual async Task<GetGridSummaryOutDto> GetGridSummaryAsync(GetGridSummaryInDto inDto, Type viewType = null)
        {
            if (viewType == null)
            {
                viewType = typeof(TViewDto);
            }

            var summaryQuery = this.GetGridDataQuery(inDto.GridInDto, viewType) as IQueryable<object>;
            var result = new GetGridSummaryOutDto();
            result.Data = await summaryQuery.FirstOrDefaultAsync();
            return result;
        }

        /// <summary>
        /// 导出表格数据
        /// </summary>
        /// <param name="inDto">获取导出表格数据输入dto</param>
        /// <param name="viewType">默认查询的view的类型</param>
        /// <returns>dto对象</returns>
        public virtual async Task<FileContentResult> GetGridExcelAsync(GetGridListInDto inDto, Type viewType = null)
        {
            if (viewType == null)
            {
                viewType = typeof(TViewDto);
            }

            var result = await this.GetGridDataResult(inDto, viewType);
            inDto.ColName = Regex.Replace(inDto.ColName, @"\(.*?\)", string.Empty);
            List<string> colNames = inDto.ColName.Split(",").ToList();
            List<string> fieldNames = inDto.FieldName.Split(",").ToList();

            // 定义导出的列的名称和字段的名称
            Dictionary<string, string> dicColField = new Dictionary<string, string>();
            for (int i = 0; i < colNames.Count; i++)
            {
                // 将首字母改为大写
                dicColField.Add(colNames[i], fieldNames[i].ToCamel());
            }

            // 如果没有数据加入首行
            if (result.DataList.Count == 0)
            {
                // view的处理
                if (inDto.ViewName.Contains("_"))
                {
                    inDto.ViewName = inDto.ViewName.Replace("_", string.Empty).ToCamel();
                }

                var namedto = $"new {inDto.ViewName}()".Execute() as dynamic;
                result.DataList.Add(namedto);
            }

            var stream = YdmExcelHelper.GetExcelForList(result.DataList, dicColField);
            FileContentResult returnFile = new FileContentResult(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            returnFile.FileDownloadName = $"{inDto.ExcelTitle}.xlsx";
            return returnFile;
        }

        /// <summary>
        /// 获取 流水号 db.GetFlowNumber("CY10") 没传就是当前表的流水号
        /// </summary>
        /// <param name="tableName">表的名称</param>
        /// <returns>表的流水号值</returns>
        public string GetFlowNumber(string tableName = null)
        {
            var db = this.GetDbContextMy();
            if (tableName == null)
            {
                // 获取Entity的名称
                tableName = typeof(TEntity).GetCustomAttributes(false).OfType<TableAttribute>().FirstOrDefault()?.Name;
            }

            return db.GetFlowNumber(tableName);
        }

        /// <summary>
        /// 获取单个的dto对象
        /// </summary>
        /// <param name="primaryKey">获取对象转成dto</param>
        /// <returns>dto对象</returns>
        public virtual async Task<TViewDto> GetViewDtoAsync(TPrimaryKey primaryKey)
        {
            var db = this.GetDbContextMy();
            var func = this.CreateViewEqualityExpressionForId(primaryKey);
            TView view = await db.Query<TView>().FirstOrDefaultAsync(func);
            TViewDto viewDto = this._objectMapper.Map<TViewDto>(view);
            return viewDto;
        }

        /// <summary>   
        ///  视图分页
        /// </summary>
        /// <code>
        /// <![CDATA[
        ///  PagedInputDto pagedInputDto = new PagedInputDto()        ///                 {        ///                     PageIndex = 1,        ///                     PageSize = 10,        ///                     Order = "StuName desc"        ///                 };        ///                 pagedInputDto.Filter = new PageFilterDto()        ///                 {        ///                     Type = "and",        ///                     Conditions = new System.Collections.Generic.List<Condition>()        ///                     {        ///                         new Condition() { Attribute = "StuName", Datatype = "nvarchar", Operatoer = "like", Value = "0" },        ///                         new Condition() { Attribute = "Birthday", Datatype = "int", Operatoer = "null" }        ///                     },        ///                     Filters = new System.Collections.Generic.List<PageFilterDto>()        ///                     {        ///                         new PageFilterDto()        ///                         {        ///                             Type = "or",        ///                             Conditions = new System.Collections.Generic.List<Condition>()        ///                             {        ///                                 new Condition() { Attribute = "ApproveState", Datatype = "nvarchar",        ///                                     Operatoer = "eq", Value = "审核中" }        ///                             }        ///                         }        ///                     }        ///                 };        ///                 var pagedResult = service.GetPage(pagedInputDto);
        /// ]]>
        /// </code>
        /// <param name="pagedInputDto">分页输入对象</param>
        /// <returns>分页对象</returns>
        public virtual async Task<MyPagedResult<TViewDto>> GetViewPageAsync(PagedInputDto pagedInputDto)
        {
            var db = this.GetDbContextMy();
            db.ChangeToRead();
            var pageResult = await db.Query<TView>().GetPageAsync<TView, TViewDto>(pagedInputDto);
            return pageResult;
        }

        /// <summary>   
        ///  视图分页 通过select的方式查询
        /// </summary>
        /// <code>
        /// <![CDATA[
        ///  PagedInputDto pagedInputDto = new PagedInputDto()        ///                 {        ///                     PageIndex = 1,        ///                     PageSize = 10,        ///                     Order = "StuName desc",        ///                     Select= "new(CompanyName as Name, Phone)"        ///                 };        ///                 pagedInputDto.Filter = new PageFilterDto()        ///                 {        ///                     Type = "and",        ///                     Conditions = new System.Collections.Generic.List<Condition>()        ///                     {        ///                         new Condition() { Attribute = "StuName", Datatype = "nvarchar", Operatoer = "like", Value = "0" },        ///                         new Condition() { Attribute = "Birthday", Datatype = "int", Operatoer = "null" }        ///                     },        ///                     Filters = new System.Collections.Generic.List<PageFilterDto>()        ///                     {        ///                         new PageFilterDto()        ///                         {        ///                             Type = "or",        ///                             Conditions = new System.Collections.Generic.List<Condition>()        ///                             {        ///                                 new Condition() { Attribute = "ApproveState", Datatype = "nvarchar",        ///                                     Operatoer = "eq", Value = "审核中" }        ///                             }        ///                         }        ///                     }        ///                 };        ///                 var pagedResult = service.GetPage(pagedInputDto);
        /// ]]>
        /// </code>
        /// <param name="pagedInputDto">分页输入对象</param>
        /// <returns>分页对象</returns>
        public virtual async Task<MyPagedResult<object>> GetViewPageSelectAsync(PagedInputDto pagedInputDto)
        {
            var db = this.GetDbContextMy();
            db.ChangeToRead();
            var pageResult = await db.Query<TView>().GetPageAsync<TView, object>(pagedInputDto);
            return pageResult;
        }

        /// <summary>   
        ///  分页
        /// </summary>
        /// <code>
        /// <![CDATA[
        ///  PagedInputDto pagedInputDto = new PagedInputDto()        ///                 {        ///                     PageIndex = 1,        ///                     PageSize = 10,        ///                     Order = "StuName desc"        ///                 };        ///                 pagedInputDto.Filter = new PageFilterDto()        ///                 {        ///                     Type = "and",        ///                     Conditions = new System.Collections.Generic.List<Condition>()        ///                     {        ///                         new Condition() { Attribute = "StuName", Datatype = "nvarchar", Operatoer = "like", Value = "0" },        ///                         new Condition() { Attribute = "Birthday", Datatype = "int", Operatoer = "null" }        ///                     },        ///                     Filters = new System.Collections.Generic.List<PageFilterDto>()        ///                     {        ///                         new PageFilterDto()        ///                         {        ///                             Type = "or",        ///                             Conditions = new System.Collections.Generic.List<Condition>()        ///                             {        ///                                 new Condition() { Attribute = "ApproveState", Datatype = "nvarchar",        ///                                     Operatoer = "eq", Value = "审核中" }        ///                             }        ///                         }        ///                     }        ///                 };        ///                 var pagedResult = service.GetPage(pagedInputDto);
        /// ]]>
        /// </code>
        /// <param name="pagedInputDto">分页输入对象</param>
        /// <returns>分页对象</returns>
        public virtual async Task<MyPagedResult<TEntityDto>> GetPageAsync(PagedInputDto pagedInputDto)
        {
            var pageResult = await base.GetAll().GetPageAsync<TEntity, TEntityDto>(pagedInputDto);
            return pageResult;
        }

        /// <summary>
        /// 根据输入的dto创建对象
        /// </summary>
        /// <param name="input">创建输入的dto</param>
        /// <returns>展示的dto</returns>
        public virtual async Task<TEntityDto> CreateByDtoAsync(TCreateInput input)
        {
            var entity = this._objectMapper.Map<TEntity>(input);
            entity = await base.InsertAsync(entity);
            base.Context.SaveChanges();
            return entity.MapTo<TEntityDto>();
        }

        /// <summary>
        /// 更新的dto
        /// </summary>
        /// <param name="input">输入对象</param>
        /// <returns>展示的Dto</returns>
        public virtual async Task<TEntityDto> UpdateByDtoAsync(TUpdateInput input)
        {
            // 找出实体
            TEntity oldEntity = await base.GetAsync(input.Id);

            // 对比变化(排除空值)
            TEntity entity = input.YdmMapTo(oldEntity);

            this.SetNoTrack(input.Id, entity);
            entity = await base.UpdateAsync(entity);

            await this.SaveChangeAsync();

            return entity.MapTo<TEntityDto>();
        }

        /// <summary>
        /// 删除方法重写
        /// </summary>
        /// <param name="id">id值</param>
        /// <returns>假删除返回任务</returns>
        public virtual async Task DeleteByIdAsync(TPrimaryKey id)
        {
            await base.DeleteAsync(id);
        }

        ///// <summary>
        ///// 删除方法重写
        ///// </summary>
        ///// <param name="id">id值</param>
        ///// <returns>假删除返回任务</returns>
        //public override async Task DeleteAsync(TPrimaryKey id)
        //{
        //    //// 找出实体
        //    //var oldEntity = await base.GetAsync(id);
        //    //oldEntity.IsDeleted = 1;

        //    await base.DeleteByIdAsync(id);
        //}

        /// <summary>
        /// 获取表格数据的Query
        /// </summary>
        /// <param name="inDto">The in dto.</param>
        /// <param name="viewType">Type of the view.</param>
        /// <param name="userQuery">用户自定义query对象用于一些特殊的查询</param>
        /// <returns> 表格数据</returns>
        public virtual IQueryable<object> GetGridDataQuery(GetGridListInDto inDto, Type viewType, IQueryable<object> userQuery = null)
        {
            var propViewVaule = this.GetGridQuery(inDto, viewType, out var pagedInputDto, userQuery);
            Assembly autoAssembly = Assembly.Load("Ydm.Abp.EntityFrameworkCore");
            var pageMethodinfo = autoAssembly.GetExtensionMethods("GetdPageQuery").FirstOrDefault();
            dynamic result = pageMethodinfo.MakeGenericMethod(viewType)
              .Invoke(null, new object[] { propViewVaule, pagedInputDto });
            return result;
        }

        /// <summary>
        /// 获取表格数据
        /// </summary>
        /// <param name="inDto">The in dto.</param>
        /// <param name="viewType">Type of the view.</param>
        /// <param name="userQuery">用户自定义query对象用于一些特殊的查询</param>
        /// <returns> 表格数据</returns>
        public virtual async Task<dynamic> GetGridDataResult(GetGridListInDto inDto, Type viewType, IQueryable<object> userQuery = null)
        {
            var propViewVaule = this.GetGridQuery(inDto, viewType, out var pagedInputDto, userQuery);

            // 缓存getviewpage方法
            MethodInfo pageMethodinfo = AppConfigConsts.GetPageAsyncMethodInfo;
            if (pageMethodinfo == null)
            {
                Assembly autoAssembly = Assembly.Load("Ydm.Abp.EntityFrameworkCore");
                pageMethodinfo = autoAssembly.GetExtensionMethods("GetPageAsync").FirstOrDefault();
                AppConfigConsts.GetPageAsyncMethodInfo = pageMethodinfo;
            }

            dynamic result = await pageMethodinfo.MakeGenericMethod(viewType, typeof(object))
                .InvokeAsync(null, new object[] { propViewVaule, pagedInputDto });

            return result;
        }

        /// <summary>
        /// 获取表格数据
        /// </summary>
        /// <param name="inDto">The in dto.</param>
        /// <param name="viewType">Type of the view.</param>
        /// <param name="pagedInputDto">分页对象</param>
        /// <param name="userQuery">用户自定义query对象用于一些特殊的查询</param>
        /// <returns> 表格数据</returns>
        private IQueryable<object> GetGridQuery(GetGridListInDto inDto, Type viewType, out PagedInputDto pagedInputDto, IQueryable<object> userQuery = null)
        {
            var db = this.GetDbContextMy();

            if (!string.IsNullOrEmpty(inDto.Sort))
            {
                inDto.Order = inDto.Sort + " " + inDto.Order;
            }

            if (!string.IsNullOrEmpty(inDto.Select))
            {
                inDto.Select = $"new({inDto.Select})";
            }

            if (inDto.Select.IsNullOrEmpty())
            {
                inDto.Select = $"new({inDto.FieldName})";
            }

            pagedInputDto = new PagedInputDto()
            {
                PageSize = inDto.Rows.ToDefault(99999),
                PageIndex = inDto.Page.ToDefault(1),
                Order = inDto.Order,
                Select = inDto.Select
            };

            if (!string.IsNullOrEmpty(inDto.Filter))
            {
                pagedInputDto.Filter = JsonConvert.DeserializeObject<PageFilterDto>(inDto.Filter);
            }

            if (!inDto.FilterRules.IsNullOrEmpty() && inDto.FilterRules != "[]")
            {
                // 有过滤条件那么要加上
                if (pagedInputDto.Filter == null)
                {
                    pagedInputDto.Filter = new PageFilterDto()
                    {
                        Type = "and",
                        InnerType = "and",
                        Conditions = new List<Condition>()
                    };
                }

                List<JuiFilterDto> filterRules = JsonConvert.DeserializeObject<List<JuiFilterDto>>(inDto.FilterRules);

                // 把JUi的filter构造我们的filter
                foreach (var filterRule in filterRules)
                {
                    if (!filterRule.Field.IsNullOrEmpty() && !filterRule.Value.IsNullOrEmpty())
                    {
                        var fieldType = viewType.GetProperty(filterRule.Field.ToCamel()).PropertyType;
                        Condition condition = new Condition()
                        {
                            Attribute = filterRule.Field,
                            Value = filterRule.Value,
                            Datatype = fieldType.GetDbType().ToString()
                        };

                        // 枚举的话那么需要 用等于，其他的不是字符串也都要用等于进行初始化
                        if (filterRule.Op.ToLower() == "contains" && ((condition.Datatype.ToLower() != "varchar" && condition.Datatype.ToLower() != "nvarchar") || fieldType.IsEnum))
                        {
                            condition.Operatoer = AppConfigConsts.JuiOps["equal"];
                        }
                        else
                        {
                            condition.Operatoer = AppConfigConsts.JuiOps[filterRule.Op];
                        }

                        pagedInputDto.Filter.Conditions.Add(condition);
                    }

                }
            }

            // 当前仓储的通过getView获取
            IQueryable<object> propViewVaule = this.GetView(true);

            // 不是当前仓储的 比如统计视图
            if (viewType != typeof(TViewDto))
            {
                if (userQuery == null)
                {
                    string viewName = inDto.ViewName.ToCamel();
                    PropertyInfo prop = db.GetType().GetProperty(viewName);
                    propViewVaule = (IQueryable<object>)prop.GetValue(db);
                }
                else
                {
                    propViewVaule = userQuery;
                }
            }

            if (inDto.IsDisableFilter == 1)
            {
                propViewVaule = propViewVaule.AsNoFilter();
            }

            if (!inDto.AdvanceFilter.IsNullOrEmpty() && inDto.AdvanceFilter != "[]")
            {
                List<JUIAdvanceFilterDto> filters = JsonConvert.DeserializeObject<List<JUIAdvanceFilterDto>>(inDto.AdvanceFilter);

                string where = string.Empty;
                List<object> pars = new List<object>();
                for (int i = 0; i < filters.Count; i++)
                {
                    if (!filters[i].Field.IsNullOrEmpty())
                    {
                        string join = filters[i].Join;
                        if (i == 0)
                        {
                            join = string.Empty;
                        }

                        where += string.Format(" " + join + " " + filters[i].Lb + filters[i].Field + AppConfigConsts.JuiAdvanceOps[filters[i].Op] + filters[i].Rb + " ", "@" + i);
                        var fieldType = viewType.GetProperty(filters[i].Field.ToCamel()).PropertyType;
                        string typeStr = fieldType.ToString();
                        if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Nullable<>))
                        {
                            typeStr = fieldType.GetGenericArguments()[0].ToString();
                        }

                        object paramValue = filters[i].Value.ToObjectValue(typeStr);
                        pars.Add(paramValue);
                    }
                }

                if (where != string.Empty)
                {
                    propViewVaule = propViewVaule.Where(where, pars.ToArray());
                }
            }

            return propViewVaule;
        }

        /// <summary>
        /// 设置不跟着当前实体
        /// </summary>
        /// <param name="entryId">老的实体的ID</param>
        /// <param name="entity">新实体</param>
        /// <remarks>ydm 2019-07-17</remarks>
        private void SetNoTrack(TPrimaryKey entryId, TEntity entity)
        {
            var context = this.GetDbContextMy();
            var local = context.Set<TEntity>()
                .Local
                .FirstOrDefault(entry => entry.Id.Equals(entryId));
            if (local != null)
            {
                context.Entry(local).State = EntityState.Detached;
            }

            context.Entry(entity).State = EntityState.Modified;
        }

        private Expression<Func<TView, bool>> CreateViewEqualityExpressionForId(TPrimaryKey id)
        {
            var lambdaParam = Expression.Parameter(typeof(TView));

            var lambdaBody = Expression.Equal(
                Expression.PropertyOrField(lambdaParam, "Id"),
                Expression.Constant(id, typeof(TPrimaryKey))
                );

            return Expression.Lambda<Func<TView, bool>>(lambdaBody, lambdaParam);
        }

    }

}
